﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;

namespace EasyTrader.Signal
{
    using PriceSignalList = List<PriceSignal>;
    public class SignalManager
    {
        private double m_TotalProfit = 0;
        public double TotalProfit
        {
            get { return m_TotalProfit; }
            set { m_TotalProfit = value; }
        }

        private double m_CurProfit = 0;
        public double CurProfit
        {
            get { return m_CurProfit; }
            set { m_CurProfit = value; }
        }

        // 이 함수는 시그널 목록을 가지고 수익을 계산합니다.
        public double CalcTotalProfit(double a_CurVal)
        {
            if (m_PriceSignalList.Count < 1)
                return m_TotalProfit;
            m_TotalProfit = 0;
            int count = m_PriceSignalList.Count;
            PriceSignal lastSignal = m_PriceSignalList[count - 1];
            double deltaY = 0;
            for (int i = 1; i < count; i++)
            {
                PriceSignal curSignal = m_PriceSignalList[i];
                PriceSignal prevSignal = m_PriceSignalList[i - 1];
                deltaY = curSignal.Y - prevSignal.Y;
                // 매수 신호일 때
                if (curSignal.Type == GlobalVar.SignalBuy)
                {
                    if (prevSignal.Type == GlobalVar.SignalSell)
                    {
                        m_TotalProfit += (-deltaY * 50);
                        m_TotalProfit -= GlobalVar.Fare;
                        m_TotalProfit -= GlobalVar.Slipage;
                    }
                }
                // 매도 신호일 때
                else if (curSignal.Type == GlobalVar.SignalSell)
                {
                    if (prevSignal.Type == GlobalVar.SignalBuy)
                    {
                        m_TotalProfit += (deltaY * 50);
                        m_TotalProfit -= GlobalVar.Fare;
                        m_TotalProfit -= GlobalVar.Slipage;
                    }
                }
                // 매수 청산 신호일 때
                else if (curSignal.Type == GlobalVar.SignalExitBuy)
                {
                    if (prevSignal.Type == GlobalVar.SignalBuy)
                    {
                        m_TotalProfit += (deltaY * 50);
                        m_TotalProfit -= GlobalVar.Fare;
                        m_TotalProfit -= GlobalVar.Slipage;
                    }
                }
                // 매도 청산 신호일 때
                else if (curSignal.Type == GlobalVar.SignalExitSell)
                {
                    if (prevSignal.Type == GlobalVar.SignalSell)
                    {
                        m_TotalProfit += (-deltaY * 50);
                        m_TotalProfit -= GlobalVar.Fare;
                        m_TotalProfit -= GlobalVar.Slipage;
                    }
                }
            }

            deltaY = Math.Abs(a_CurVal - lastSignal.Y);
            if (lastSignal.Type == GlobalVar.SignalBuy)
            {
                if (a_CurVal > lastSignal.Y)
                {
                    m_TotalProfit += (deltaY * 50);
                    m_TotalProfit -= GlobalVar.Fare;
                    m_TotalProfit -= GlobalVar.Slipage;
                }
                else
                {
                    m_TotalProfit += (-deltaY * 50);
                    m_TotalProfit -= GlobalVar.Fare;
                    m_TotalProfit -= GlobalVar.Slipage;
                }
            }
            else if (lastSignal.Type == GlobalVar.SignalSell)
            {
                if (a_CurVal < lastSignal.Y)
                {
                    m_TotalProfit += (deltaY * 50);
                    m_TotalProfit -= GlobalVar.Fare;
                    m_TotalProfit -= GlobalVar.Slipage;
                }
                else
                {
                    m_TotalProfit += (-deltaY * 50);
                    m_TotalProfit -= GlobalVar.Fare;
                    m_TotalProfit -= GlobalVar.Slipage;
                }
            }

            return m_TotalProfit;
        }

        public double GetDayOpen()
        {
            EasyTrader.DataSet.FutOptChartTable table = m_EasyTraderDataSet.GetFutOptChartTable();
            int count = table.Rows.Count;
            if (count == 0)
                return -1.0;
            DataRow curRow = table.Rows[0];
            object openVal = curRow["시가"];
            return Convert.ToDouble(openVal);
        }

        // 이 함수는 시그널 목록을 가지고 수익을 계산합니다.
        public double CalcTotalProfit(PriceSignalList a_SignalList, double a_CurVal)
        {
            double TotalProfit = 0;
            if (a_SignalList == null)
                return TotalProfit;
            if (a_SignalList.Count < 1)
                return TotalProfit;
            int count = a_SignalList.Count;
            PriceSignal lastSignal = a_SignalList[count - 1];
            double deltaY = 0;
            for (int i = 1; i < count; i++)
            {
                PriceSignal curSignal = a_SignalList[i];
                PriceSignal prevSignal = a_SignalList[i - 1];
                deltaY = curSignal.Y - prevSignal.Y;
                // 매수 신호일 때
                if (curSignal.Type == GlobalVar.SignalBuy)
                {
                    if (prevSignal.Type == GlobalVar.SignalSell)
                    {
                        TotalProfit += (-deltaY * 50);
                        TotalProfit -= GlobalVar.Fare;
                        TotalProfit -= GlobalVar.Slipage;
                    }
                }
                // 매도 신호일 때
                else if (curSignal.Type == GlobalVar.SignalSell)
                {
                    if (prevSignal.Type == GlobalVar.SignalBuy)
                    {
                        TotalProfit += (deltaY * 50);
                        TotalProfit -= GlobalVar.Fare;
                        TotalProfit -= GlobalVar.Slipage;
                    }
                }
                // 매수 청산 신호일 때
                else if (curSignal.Type == GlobalVar.SignalExitBuy)
                {
                    if (prevSignal.Type == GlobalVar.SignalBuy)
                    {
                        TotalProfit += (deltaY * 50);
                        TotalProfit -= GlobalVar.Fare;
                        TotalProfit -= GlobalVar.Slipage;
                    }
                }
                // 매도 청산 신호일 때
                else if (curSignal.Type == GlobalVar.SignalExitSell)
                {
                    if (prevSignal.Type == GlobalVar.SignalSell)
                    {
                        TotalProfit += (-deltaY * 50);
                        TotalProfit -= GlobalVar.Fare;
                        TotalProfit -= GlobalVar.Slipage;
                    }
                }
            }

            deltaY = Math.Abs(a_CurVal - lastSignal.Y);
            if (lastSignal.Type == GlobalVar.SignalBuy)
            {
                if (a_CurVal > lastSignal.Y)
                {
                    TotalProfit += (deltaY * 50);
                    TotalProfit -= GlobalVar.Fare;
                    TotalProfit -= GlobalVar.Slipage;
                }
                else
                {
                    TotalProfit += (-deltaY * 50);
                    TotalProfit -= GlobalVar.Fare;
                    TotalProfit -= GlobalVar.Slipage;
                }
            }
            else if (lastSignal.Type == GlobalVar.SignalSell)
            {
                if (a_CurVal < lastSignal.Y)
                {
                    TotalProfit += (deltaY * 50);
                    TotalProfit -= GlobalVar.Fare;
                    TotalProfit -= GlobalVar.Slipage;
                }
                else
                {
                    TotalProfit += (-deltaY * 50);
                    TotalProfit -= GlobalVar.Fare;
                    TotalProfit -= GlobalVar.Slipage;
                }
            }

            return TotalProfit;
        }


        // 이 함수는 현재 신호에 대해서만 수익을 계산합니다.
        public double CalcCurProfit(double a_CurVal)
        {
            m_CurProfit = 0;
            if (m_PriceSignalList.Count < 1)
                return m_CurProfit;
            int count = m_PriceSignalList.Count;
            if (count == 0)
                return m_CurProfit;

            PriceSignal lastSignal = m_PriceSignalList[count - 1];

            double deltaY = 0.0;
            deltaY = Math.Abs(a_CurVal - lastSignal.Y);
            if (lastSignal.Type == GlobalVar.SignalBuy)
            {
                if (a_CurVal > lastSignal.Y)
                {
                    m_CurProfit += (deltaY * 50);
                    m_CurProfit -= GlobalVar.Fare;
                    m_CurProfit -= GlobalVar.Slipage;
                }
                else
                {
                    m_CurProfit += (-deltaY * 50);
                    m_CurProfit -= GlobalVar.Fare;
                    m_CurProfit -= GlobalVar.Slipage;
                }
            }
            else if (lastSignal.Type == GlobalVar.SignalSell)
            {
                if (a_CurVal < lastSignal.Y)
                {
                    m_CurProfit += (deltaY * 50);
                    m_CurProfit -= GlobalVar.Fare;
                    m_CurProfit -= GlobalVar.Slipage;
                }
                else
                {
                    m_CurProfit += (-deltaY * 50);
                    m_CurProfit -= GlobalVar.Fare;
                    m_CurProfit -= GlobalVar.Slipage;
                }
            }

            return m_CurProfit;
        }

        // 이 함수는 현재 신호에 대해서만 수익을 계산합니다.
        public double CalcCurProfit(PriceSignalList a_SignalList, double a_CurVal)
        {
            double CurProfit = 0;
            if (a_SignalList.Count < 1)
                return CurProfit;
            int count = a_SignalList.Count;
            if (count == 0)
                return CurProfit;

            PriceSignal lastSignal = a_SignalList[count - 1];

            double deltaY = 0.0;
            deltaY = Math.Abs(a_CurVal - lastSignal.Y);
            if (lastSignal.Type == GlobalVar.SignalBuy)
            {
                if (a_CurVal > lastSignal.Y)
                {
                    CurProfit += (deltaY * 50);
                    CurProfit -= GlobalVar.Fare;
                    CurProfit -= GlobalVar.Slipage;
                }
                else
                {
                    CurProfit += (-deltaY * 50);
                    CurProfit -= GlobalVar.Fare;
                    CurProfit -= GlobalVar.Slipage;
                }
            }
            else if (lastSignal.Type == GlobalVar.SignalSell)
            {
                if (a_CurVal < lastSignal.Y)
                {
                    CurProfit += (deltaY * 50);
                    CurProfit -= GlobalVar.Fare;
                    CurProfit -= GlobalVar.Slipage;
                }
                else
                {
                    CurProfit += (-deltaY * 50);
                    CurProfit -= GlobalVar.Fare;
                    CurProfit -= GlobalVar.Slipage;
                }
            }

            return CurProfit;
        }

        public void ClearSignalList()
        {
            m_PriceSignalList.Clear();
        }

        public void ClearSignalList(PriceSignalList a_SignalList)
        {
            a_SignalList.Clear();
        }

        protected bool IsLastSignalSame(int a_SignalType)
        {
            if (m_PriceSignalList == null)
                return false;

            int signalCount = m_PriceSignalList.Count;
            if (signalCount == 0)
            {
                return false;
            }

            PriceSignal prevSignal = m_PriceSignalList[signalCount - 1];
            if (prevSignal.Type == a_SignalType)
            {
                return true;
            }
            else
            {
                return false;
            }
        }

        public bool IsLastSignalSame(PriceSignalList a_SignalList, int a_SignalType)
        {
            if (a_SignalList == null)
                return false;

            int signalCount = a_SignalList.Count;
            if (signalCount == 0)
            {
                return false;
            }

            PriceSignal prevSignal = a_SignalList[signalCount - 1];
            if (prevSignal.Type == a_SignalType)
            {
                return true;
            }
            else
            {
                return false;
            }
        }

        // 신호가 동시간 대에 있는지 초의 차이를 통해서 확인한다.
        protected bool IsLastSignalSameTime(int a_SignalTime)
        {
            if (m_PriceSignalList == null)
                return false;

            int signalCount = m_PriceSignalList.Count;
            if (signalCount == 0)
            {
                return false;
            }

            PriceSignal prevSignal = m_PriceSignalList[signalCount - 1];
            DateTime now = DateTime.Now;
            string curTime = a_SignalTime.ToString();
            string prevTime = prevSignal.Time.ToString();
            if (curTime.Length < 5 || prevTime.Length < 5)
            {
                GlobalVar.WriteLog(GlobalVar.TimeFormatError);
                return false;
            }
            string curSecond = curTime.Substring(curTime.Length - 2, 2);
            string prevSecond = prevTime.Substring(prevTime.Length - 2, 2);
            string curMin = curTime.Substring(curTime.Length - 4, 2);
            string prevMin = prevTime.Substring(prevTime.Length - 4, 2);
            int curSecondVal = Convert.ToInt32(curSecond);
            int prevSecondVal = Convert.ToInt32(prevSecond);
            int curMinVal = Convert.ToInt32(curMin);
            int prevMinVal = Convert.ToInt32(prevMin);
            string curHour = curTime.Substring(0, curTime.Length - 4);
            string prevHour = prevTime.Substring(0, prevTime.Length - 4);
            int curHourVal = Convert.ToInt32(curHour);
            int prevHourVal = Convert.ToInt32(prevHour);
            DateTime prevTimeVal = new DateTime(now.Year, now.Month, now.Day, prevHourVal, prevMinVal, prevSecondVal);
            DateTime curTimeVal = new DateTime(now.Year, now.Month, now.Day, curHourVal, curMinVal, curSecondVal);
            TimeSpan curSpan = curTimeVal - prevTimeVal;
            double tSeconds = curSpan.TotalSeconds;

            // 시간차이가 60초 안이면 동시간대에 발생한 것으로 한다.
            if (Math.Abs(tSeconds) < GlobalVar.MinSignalInterval)
                return true;
            else // 시간차이가 60초 이상되었을 때는 다른 신호로 본다.
                return false;
        }

        // 신호가 동시간 대에 있는지 초의 차이를 통해서 확인한다.
        public bool IsLastSignalSameTime(PriceSignalList a_SignalList, int a_SignalTime)
        {
            if (a_SignalList == null)
                return false;

            int signalCount = a_SignalList.Count;
            if (signalCount == 0)
            {
                return false;
            }

            PriceSignal prevSignal = a_SignalList[signalCount - 1];
            DateTime now = DateTime.Now;
            string curTime = a_SignalTime.ToString();
            string prevTime = prevSignal.Time.ToString();
            if (curTime.Length < 5 || prevTime.Length < 5)
            {
                GlobalVar.WriteLog(GlobalVar.TimeFormatError);
                return false;
            }
            string curSecond = curTime.Substring(curTime.Length - 2, 2);
            string prevSecond = prevTime.Substring(prevTime.Length - 2, 2);
            string curMin = curTime.Substring(curTime.Length - 4, 2);
            string prevMin = prevTime.Substring(prevTime.Length - 4, 2);
            int curSecondVal = Convert.ToInt32(curSecond);
            int prevSecondVal = Convert.ToInt32(prevSecond);
            int curMinVal = Convert.ToInt32(curMin);
            int prevMinVal = Convert.ToInt32(prevMin);
            string curHour = curTime.Substring(0, curTime.Length - 4);
            string prevHour = prevTime.Substring(0, prevTime.Length - 4);
            int curHourVal = Convert.ToInt32(curHour);
            int prevHourVal = Convert.ToInt32(prevHour);
            DateTime prevTimeVal = new DateTime(now.Year, now.Month, now.Day, prevHourVal, prevMinVal, prevSecondVal);
            DateTime curTimeVal = new DateTime(now.Year, now.Month, now.Day, curHourVal, curMinVal, curSecondVal);
            TimeSpan curSpan = curTimeVal - prevTimeVal;
            double tSeconds = curSpan.TotalSeconds;

            // 시간차이가 60초 안이면 동시간대에 발생한 것으로 한다.
            if (Math.Abs(tSeconds) < GlobalVar.MinSignalInterval)
                return true;
            else // 시간차이가 60초 이상되었을 때는 다른 신호로 본다.
                return false;
        }

        protected PriceSignal GetLastSignal()
        {
            if (m_PriceSignalList == null)
                return null;

            int signalCount = m_PriceSignalList.Count;
            if (signalCount == 0)
            {
                return null;
            }

            PriceSignal prevSignal = m_PriceSignalList[signalCount - 1];
            return prevSignal;
        }

        public PriceSignal GetLastSignal(PriceSignalList a_SignalList)
        {
            if (a_SignalList == null)
                return null;

            int signalCount = a_SignalList.Count;
            if (signalCount == 0)
            {
                return null;
            }

            PriceSignal prevSignal = a_SignalList[signalCount - 1];
            return prevSignal;
        }

        public PriceSignal GetPrevSignal(PriceSignalList a_SignalList)
        {
            if (a_SignalList == null)
                return null;

            int signalCount = a_SignalList.Count;
            if (signalCount < 2)
            {
                return null;
            }

            PriceSignal prevSignal = a_SignalList[signalCount - 2];
            return prevSignal;
        }

        // 가장 최근의 전환신호를 찾아서 가져온다.
        protected PriceSignal GetLastTransSignal()
        {
            if (m_PriceSignalList == null)
                return null;

            int signalCount = m_PriceSignalList.Count;
            if (signalCount == 0)
            {
                return null;
            }

            for (int i = signalCount - 1; i >= 0; i--)
            {
                EasyTrader.Signal.PriceSignal curSignal = m_PriceSignalList[i];
                if (curSignal.SignalState == GlobalVar.SignalStateTrans)
                    return curSignal;
            }

            return null;
        }
        // 신호를 신호 목록에 더한다. 이 때 중복된 신호는 피한다.
        protected void AddSignal(PriceSignal a_Signal)
        {
            if (m_PriceSignalList == null)
                return;

            int signalCount = m_PriceSignalList.Count;
            if (signalCount == 0)
            {
                m_PriceSignalList.Add(a_Signal);
                return;
            }

            PriceSignal prevSignal = m_PriceSignalList[signalCount - 1];
            if (prevSignal.Type != a_Signal.Type)
            {
                m_PriceSignalList.Add(a_Signal);
            }
        }

        public void AddSignal(PriceSignalList a_SignalList, PriceSignal a_Signal)
        {
            if (a_SignalList == null)
                return;

            int signalCount = a_SignalList.Count;
            if (signalCount == 0)
            {
                a_SignalList.Add(a_Signal);
                return;
            }

            PriceSignal prevSignal = a_SignalList[signalCount - 1];
            if (prevSignal.Type != a_Signal.Type)
            {
                a_SignalList.Add(a_Signal);
            }
        }

        protected PriceSignalList m_PriceSignalList = new PriceSignalList();
        public PriceSignalList PriceSignalList
        {
            get { return m_PriceSignalList; }
            set { m_PriceSignalList = value; }
        }

        protected DirectionDetector m_Forecaster = new DirectionDetector();
        public EasyTrader.Signal.DirectionDetector Forecaster
        {
            get { return m_Forecaster; }
            set { m_Forecaster = value; }
        }
        protected EasyTrader.ETDataSet m_EasyTraderDataSet = null;
        public EasyTrader.ETDataSet EasyTraderDataSet
        {
            get { return m_EasyTraderDataSet; }
            set { m_EasyTraderDataSet = value; }
        }

        public SignalManager()
        {
            m_EasyTraderDataSet = GlobalVar.GDataSet;
        }

        public virtual int GetSignal(int a_DataCount)
        {
            return GlobalVar.SignalNone;
        }

        public static int GetStartX(int a_EndX, int a_Range)
        {
            if (a_EndX <= 0)
                return 0;
            int startX = Math.Max(0, a_EndX - a_Range);

            return startX;
        }

        // 이 함수는 두 값을 비교하여 수렴과 발산을 찾아 낸다.
        // 항상 첫째는 매수의 입장에서 둘째는 매도의 입장에서 사용할 것을 권장한다.
        public static string FindInvDivString(ForecastingInfo a_FirstInfo, ForecastingInfo a_SecondInfo)
        {
            string invdiv = "None";
            ForecastingInfo firstForecast = a_FirstInfo;
            ForecastingInfo secondForecast = a_SecondInfo;
            if (firstForecast == null || secondForecast == null)
                return invdiv;
            double slopeFirst = firstForecast.EndY - firstForecast.StartY;
            double slopeSecond = secondForecast.EndY - secondForecast.StartY;
            double deltaStartY = Math.Abs(firstForecast.StartY - secondForecast.StartY);
            double deltaEndY = Math.Abs(firstForecast.EndY - secondForecast.EndY);
            int crossedVal = FindCrossedVal(firstForecast, secondForecast);
            if (crossedVal == -2)
                return invdiv;
            else if (crossedVal == 1) // 첫째가 항상 위에 
            {
                if (slopeFirst > 0)
                {
                    if (slopeSecond > 0) // 둘 다 기울기가 양일 때
                    {
                        // 둘다 상승중일 때 - 이 때는 경사도로 평가를 한다.
                        // 처음보다 간격이 더 벌어진 경우로 발산이지만 약한 발산
                        if (deltaEndY > deltaStartY)
                        {
                            // 첫째가 좀더 유리한 발산 - 첫째와 둘째가 둘 다 올라오지만 첫째가 더 강하게 올라오는 상황 - 2
                            invdiv = "FSDivFPSP";
                        }
                        else // 처음보다 간격이 좁아진 경우로 이경우는 수렴이지만 약한 수렴
                        {
                            // 둘째가 좀 더 유리한 수렴 - 첫째와 둘째가 둘다 올라오지만 둘째가 더 강하게 올라오는 상황 - (-5)
                            invdiv = "SSInvFPSP";
                        }
                    }
                    else // 첫째 기울기 양, 둘째 기울기 음
                    {
                        // 첫째가 매우 유리한 발산 - 첫째 올라가고 둘째 내려가는 상황
                        // 제일 강한 첫째 - 1
                        invdiv = "FSDivFPSM";
                    }
                }
                else // slopeFirst <= 0
                {
                    if (slopeSecond > 0) // 첫째는 음, 둘째는 양
                    {
                        // 둘째가 매우 유리한 수렴 - 첫째는 내려가고 둘째는 치고 올라오는 상황 - (-4)
                        invdiv = "SSInvFMSP";
                    }
                    else // 첫째 음, 둘째 음
                    {
                        if (deltaEndY > deltaStartY)
                        {
                            // 첫째가 좀 더 유리한 발산 - 첫째둘째 둘다 하락이지만 둘째가 더 강하게 내려가는 상황 - 6
                            invdiv = "FSDivFMSM";
                        }
                        else
                        {
                            // 둘째가 좀 더 유리한 수렴 - 첫째둘째 둘다 하락이지만 첫째가 더 강하게 내려가는 상황 - (-7)
                            invdiv = "SSInvFMSM";
                        }
                    }
                }
            }
            else if (crossedVal == 2) // 첫째가 처음엔 위에 나중엔 아래에
            {
                // 둘째가 첫째를 뚫고 올라온 상태로 둘째가 전적으로 유리한 발산 - (-3)
                invdiv = "SSCrossUp";
            }
            else if (crossedVal == 3) // 첫째가 항상 아래
            {
                if (slopeFirst > 0)
                {
                    if (slopeSecond > 0)
                    {
                        if (deltaEndY > deltaStartY)
                        {
                            // 첫째 양, 둘째 양 - 둘째가 더 강하게 올라가는 상황으로 둘째가 유리한 발산 상태 - (-2)
                            invdiv = "SSDivFPSP";
                        }
                        else
                        {
                            // 첫째 양, 둘째 양 - 첫째가 더 강하게 올라가는 상황으로 첫째가 유리한 수렴 상태 - 5
                            invdiv = "FSInvFPSP";
                        }
                    }
                    else
                    {
                        // 첫째 양, 둘째 음
                        // 첫째가 절대적으로 유리한 수렴상태 - 첫째는 올라오고 둘째는 내려가는 상태 - 4
                        invdiv = "FSInvFPSM";
                    }
                }
                else // if (slopeFirst > 0)
                {
                    if (slopeSecond > 0)
                    {
                        // 첫째 음, 둘째 양 
                        // 첫째는 내려가고 둘째는 올라가는 둘째가 매우 유리한 발산 상태  - (-1)
                        invdiv = "SSDivFMSP";
                    }
                    else
                    {
                        // 첫째 음, 둘째 음
                        if (deltaEndY > deltaStartY) // 발산
                        {
                            // 둘째 유리 - 첫째가 더 강하게 내려가는 발산으로 둘째가 유리한 상태 - (-6)
                            invdiv = "SSDivFMSM";
                        }
                        else // 수렴
                        {
                            // 첫째 유리 - 둘째가 더 강하게 내려가는 수렴으로 첫째가 유리한 상태 - 7
                            invdiv = "FSInvFMSM";
                        }
                    }
                }
            }
            else if (crossedVal == 4) // 첫째가 처음엔 아래에 나중엔 위에
            {
                // 첫째가 둘째를 뚫고 올라온 상태로 첫째가 절대적으로 유리한 발산
                // 첫째가 돌파하는 신호 - 3;
                invdiv = "FSCrossUp";
            }
            return invdiv;
        }


        protected double FindInvDivPercent(double a_CurSlope, double a_CurInvDiv)
        {
            double percent = 0.0;
            if (a_CurSlope < 0.0)
            {
                if (a_CurInvDiv == -1.0)
                    percent = -100.0;
                else if (a_CurInvDiv == -2.0)
                    percent = -(100.0 - ((100.0 * 1.0) / 18.0));
                else if (a_CurInvDiv == -3.0)
                    percent = -(100.0 - ((100.0 * 2.0) / 18.0));
                else if (a_CurInvDiv == -4.0)
                    percent = -(100.0 - ((100.0 * 3.0) / 18));
                else if (a_CurInvDiv == -5.0)
                    percent = -(100.0 - ((100.0 * 4.0) / 18.0));
                else if (a_CurInvDiv == -6.0)
                    percent = -(100.0 - ((100.0 * 5.0) / 18.0));
                else if (a_CurInvDiv == -7.0)
                    percent = -(100.0 - ((100.0 * 6.0) / 18.0));
                else if (a_CurInvDiv == -8.0)
                    percent = -(100.0 - ((100.0 * 7.0) / 18.0));
                else if (a_CurInvDiv == -9.0)
                    percent = -(100.0 - ((100.0 * 8.0) / 18.0));
                else if (a_CurInvDiv == 9.0)
                    percent = -(100.0 - ((100.0 * 9.0) / 18.0));
                else if (a_CurInvDiv == 8.0)
                    percent = -(100.0 - ((100.0 * 10.0) / 18.0));
                else if (a_CurInvDiv == 7.0)
                    percent = -(100.0 - ((100.0 * 11.0) / 18.0));
                else if (a_CurInvDiv == 6.0)
                    percent = -(100.0 - ((100.0 * 12.0) / 18.0));
                else if (a_CurInvDiv == 5.0)
                    percent = -(100.0 - ((100.0 * 13.0) / 18.0));
                else if (a_CurInvDiv == 4.0)
                    percent = -(100.0 - ((100.0 * 14.0) / 18.0));
                else if (a_CurInvDiv == 3.0)
                    percent = -(100.0 - ((100.0 * 15.0) / 18.0));
                else if (a_CurInvDiv == 2.0)
                    percent = -(100.0 - ((100.0 * 16.0) / 18.0));
                else if (a_CurInvDiv == 1.0)
                    percent = -(100.0 - ((100.0 * 17.0) / 18.0));
            }
            else if (a_CurSlope > 0)
            {
                if (a_CurInvDiv == 1.0)
                    percent = 100.0;
                else if (a_CurInvDiv == 2.0)
                    percent = (100.0 - ((100.0 * 1.0) / 18.0));
                else if (a_CurInvDiv == 3.0)
                    percent = (100.0 - ((100.0 * 2.0) / 18.0));
                else if (a_CurInvDiv == 4.0)
                    percent = (100.0 - ((100.0 * 3.0) / 18.0));
                else if (a_CurInvDiv == 5.0)
                    percent = (100.0 - ((100.0 * 4.0) / 18.0));
                else if (a_CurInvDiv == 6.0)
                    percent = (100.0 - ((100.0 * 5.0) / 18.0));
                else if (a_CurInvDiv == 7.0)
                    percent = (100.0 - ((100.0 * 6.0) / 18.0));
                else if (a_CurInvDiv == 8.0)
                    percent = (100.0 - ((100.0 * 7.0) / 18.0));
                else if (a_CurInvDiv == 9.0)
                    percent = (100.0 - ((100.0 * 8.0) / 18.0));
                else if (a_CurInvDiv == -9.0)
                    percent = (100.0 - ((100.0 * 9.0) / 18.0));
                else if (a_CurInvDiv == -8.0)
                    percent = (100.0 - ((100.0 * 10.0) / 18.0));
                else if (a_CurInvDiv == -7.0)
                    percent = (100.0 - ((100.0 * 11.0) / 18.0));
                else if (a_CurInvDiv == -6.0)
                    percent = (100.0 - ((100.0 * 12.0) / 18.0));
                else if (a_CurInvDiv == -5.0)
                    percent = (100.0 - ((100.0 * 13.0) / 18.0));
                else if (a_CurInvDiv == -4.0)
                    percent = (100.0 - ((100.0 * 14.0) / 18.0));
                else if (a_CurInvDiv == -3.0)
                    percent = (100.0 - ((100.0 * 15.0) / 18.0));
                else if (a_CurInvDiv == -2.0)
                    percent = (100.0 - ((100.0 * 16.0) / 18.0));
                else if (a_CurInvDiv == -1.0)
                    percent = (100.0 - ((100.0 * 17.0) / 18.0));
            }
            else
                percent = 0.0;

            return percent;
        }


        // 이 함수는 두 값을 비교하여 수렴과 발산을 찾아 낸다.
        // 항상 첫째는 매수의 입장에서 둘째는 매도의 입장에서 사용해야 한다.
        public static int FindInvDivType(ForecastingInfo a_FirstInfo, ForecastingInfo a_SecondInfo)
        {
            int invdiv = 0;
            ForecastingInfo firstForecast = a_FirstInfo;
            ForecastingInfo secondForecast = a_SecondInfo;
            if (firstForecast == null || secondForecast == null)
                return invdiv;
            double slopeFirst = firstForecast.EndY - firstForecast.StartY;
            double slopeSecond = secondForecast.EndY - secondForecast.StartY;
            double deltaStartY = Math.Abs(firstForecast.StartY - secondForecast.StartY);
            double deltaEndY = Math.Abs(firstForecast.EndY - secondForecast.EndY);
            int crossedVal = FindCrossedVal(firstForecast, secondForecast);
            if (crossedVal == -2)
                return invdiv;
            else if (crossedVal == 1) // 첫째가 항상 위에 
            {
                if (slopeFirst > 0)
                {
                    if (slopeSecond > 0) // 둘 다 기울기가 양일 때
                    {
                        // 둘다 상승중일 때 - 이 때는 경사도로 평가를 한다.
                        // 처음보다 간격이 더 벌어진 경우로 발산이지만 약한 발산
                        if (deltaEndY > deltaStartY)
                        {
                            // 첫째가 좀더 유리한 발산 - 첫째와 둘째가 둘 다 올라오지만 첫째가 더 강하게 올라오는 상황 - 2
                            invdiv = 4; // "FSDivFPSP";
                        }
                        else // 처음보다 간격이 좁아진 경우로 이경우는 수렴이지만 약한 수렴
                        {
                            // 둘째가 좀 더 유리한 수렴 - 첫째와 둘째가 둘다 올라오지만 둘째가 더 강하게 올라오는 상황 - (-5)
                            invdiv = -5; //"SSInvFPSP";
                        }
                    }
                    else // 첫째 기울기 양, 둘째 기울기 음
                    {
                        // 첫째가 매우 유리한 발산 - 첫째 올라가고 둘째 내려가는 상황
                        // 제일 강한 첫째 - 1
                        invdiv = 3; // "FSDivFPSM";
                    }
                }
                else // slopeFirst <= 0
                {
                    if (slopeSecond > 0) // 첫째는 음, 둘째는 양
                    {
                        // 둘째가 매우 유리한 수렴 - 첫째는 내려가고 둘째는 치고 올라오는 상황 - (-4)
                        invdiv = -6;// "SSInvFMSP";
                    }
                    else // 첫째 음, 둘째 음
                    {
                        if (deltaEndY > deltaStartY)
                        {
                            // 첫째가 좀 더 유리한 발산 - 첫째둘째 둘다 하락이지만 둘째가 더 강하게 내려가는 상황 - 6
                            invdiv = 8; // "FSDivFMSM";
                        }
                        else
                        {
                            // 둘째가 좀 더 유리한 수렴 - 첫째둘째 둘다 하락이지만 첫째가 더 강하게 내려가는 상황 - (-7)
                            invdiv = -9; // "SSInvFMSM";
                        }
                    }
                }
            }
            else if (crossedVal == 2) // 첫째가 처음엔 위에 나중엔 아래에
            {
                // 둘째가 첫째를 뚫고 올라온 상태로 둘째가 전적으로 유리한 발산 - (-3)
                invdiv = -4; // "SSCrossUp";
                if (slopeFirst > 0)
                {
                    if (slopeSecond > 0)
                    {
                        // 둘다 기울기가 양인상태
                        invdiv = -2; // SSCrossUpFPSP
                    }
                    else
                    {
                        // 이 경우는 있을 수 없음
                        invdiv = 0; // SSCrossUpFPSM
                    }
                }
                else
                {
                    if (slopeSecond > 0)
                    {
                        invdiv = -1; // SSCrossUpFMSP
                    }
                    else
                    {
                        invdiv = -7; // SSCrossUpFMSM
                    }
                }
            }
            else if (crossedVal == 3) // 첫째가 항상 아래
            {
                if (slopeFirst > 0)
                {
                    if (slopeSecond > 0)
                    {
                        if (deltaEndY > deltaStartY)
                        {
                            // 첫째 양, 둘째 양 - 둘째가 더 강하게 올라가는 상황으로 둘째가 유리한 발산 상태 - (-2)
                            invdiv = -4;// "SSDivFPSP";
                        }
                        else
                        {
                            // 첫째 양, 둘째 양 - 첫째가 더 강하게 올라가는 상황으로 첫째가 유리한 수렴 상태 - 5
                            invdiv = 5;// "FSInvFPSP";
                        }
                    }
                    else
                    {
                        // 첫째 양, 둘째 음
                        // 첫째가 절대적으로 유리한 수렴상태 - 첫째는 올라오고 둘째는 내려가는 상태 - 4
                        invdiv = 6; // "FSInvFPSM";
                    }
                }
                else // if (slopeFirst > 0)
                {
                    if (slopeSecond > 0)
                    {
                        // 첫째 음, 둘째 양 
                        // 첫째는 내려가고 둘째는 올라가는 둘째가 매우 유리한 발산 상태  - (-1)
                        invdiv = -3;// "SSDivFMSP";
                    }
                    else
                    {
                        // 첫째 음, 둘째 음
                        if (deltaEndY > deltaStartY) // 발산
                        {
                            // 둘째 유리 - 첫째가 더 강하게 내려가는 발산으로 둘째가 유리한 상태 - (-6)
                            invdiv = -8; // "SSDivFMSM";
                        }
                        else // 수렴
                        {
                            // 첫째 유리 - 둘째가 더 강하게 내려가는 수렴으로 첫째가 유리한 상태 - 7
                            invdiv = 9; // "FSInvFMSM";
                        }
                    }
                }
            }
            else if (crossedVal == 4) // 첫째가 처음엔 아래에 나중엔 위에
            {
                // 첫째가 둘째를 뚫고 올라온 상태로 첫째가 절대적으로 유리한 발산
                // 첫째가 돌파하는 신호 - 3;
                //invdiv = 4; // "FSCrossUp";
                if (slopeFirst > 0)
                {
                    if (slopeSecond > 0)
                    {
                        invdiv = 2; // FSCrossUpFPSP
                    }
                    else
                    {
                        invdiv = 1; // FSCrossUpFPSM
                    }
                }
                else
                {
                    if (slopeSecond > 0)
                    {
                        // 있을 수 없는 경우임
                        invdiv = 0;
                    }
                    else
                    {
                        invdiv = 7; // FSCrossUpFMSM
                    }
                }
            }
            return invdiv;
        }

        // 앞에것을 중심으로 두 값이 교차하였는지를 검사하여 결과를 반환한다.
        public static int FindCrossedVal(ForecastingInfo a_FirstInfo, ForecastingInfo a_SecondInfo)
        {
            if (a_FirstInfo == null || a_SecondInfo == null)
                return -2;

            if (a_FirstInfo.StartY > a_SecondInfo.StartY)
            {
                if (a_FirstInfo.EndY > a_SecondInfo.EndY)
                {
                    // No cross
                    return 1;
                }
                else
                {
                    // Cross Down
                    return 2;
                }
            }
            else
            {
                if (a_FirstInfo.EndY < a_SecondInfo.EndY)
                {
                    // No cross
                    return 3;
                }
                else
                {
                    // Cross Up
                    return 4;
                }
            }
        }
    } // class
} // name space
